/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.gruposp2p.aularest.model.controller;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import org.gruposp2p.aularest.model.Course;
import org.gruposp2p.aularest.model.Coursegroup;
import java.util.ArrayList;
import java.util.Collection;
import org.gruposp2p.aularest.model.Itemcalificable;
import org.gruposp2p.aularest.model.Absence;
import org.gruposp2p.aularest.model.Subject;
import org.gruposp2p.aularest.model.controller.exceptions.IllegalOrphanException;
import org.gruposp2p.aularest.model.controller.exceptions.NonexistentEntityException;
import org.gruposp2p.aularest.model.controller.exceptions.PreexistingEntityException;

/**
 *
 * @author jj
 */
public class SubjectJpaController {

    public SubjectJpaController() {
        emf = Persistence.createEntityManagerFactory("AulaRest_PU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Subject subject) throws PreexistingEntityException, Exception {
        if (subject.getCoursegroupCollection() == null) {
            subject.setCoursegroupCollection(new ArrayList<Coursegroup>());
        }
        if (subject.getItemcalificableCollection() == null) {
            subject.setItemcalificableCollection(new ArrayList<Itemcalificable>());
        }
        if (subject.getAbsenceCollection() == null) {
            subject.setAbsenceCollection(new ArrayList<Absence>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Course courseId = subject.getCourseId();
            if (courseId != null) {
                courseId = em.getReference(courseId.getClass(), courseId.getId());
                subject.setCourseId(courseId);
            }
            Collection<Coursegroup> attachedCoursegroupCollection = new ArrayList<Coursegroup>();
            for (Coursegroup coursegroupCollectionCoursegroupToAttach : subject.getCoursegroupCollection()) {
                coursegroupCollectionCoursegroupToAttach = em.getReference(coursegroupCollectionCoursegroupToAttach.getClass(), coursegroupCollectionCoursegroupToAttach.getId());
                attachedCoursegroupCollection.add(coursegroupCollectionCoursegroupToAttach);
            }
            subject.setCoursegroupCollection(attachedCoursegroupCollection);
            Collection<Itemcalificable> attachedItemcalificableCollection = new ArrayList<Itemcalificable>();
            for (Itemcalificable itemcalificableCollectionItemcalificableToAttach : subject.getItemcalificableCollection()) {
                itemcalificableCollectionItemcalificableToAttach = em.getReference(itemcalificableCollectionItemcalificableToAttach.getClass(), itemcalificableCollectionItemcalificableToAttach.getId());
                attachedItemcalificableCollection.add(itemcalificableCollectionItemcalificableToAttach);
            }
            subject.setItemcalificableCollection(attachedItemcalificableCollection);
            Collection<Absence> attachedAbsenceCollection = new ArrayList<Absence>();
            for (Absence absenceCollectionAbsenceToAttach : subject.getAbsenceCollection()) {
                absenceCollectionAbsenceToAttach = em.getReference(absenceCollectionAbsenceToAttach.getClass(), absenceCollectionAbsenceToAttach.getId());
                attachedAbsenceCollection.add(absenceCollectionAbsenceToAttach);
            }
            subject.setAbsenceCollection(attachedAbsenceCollection);
            em.persist(subject);
            if (courseId != null) {
                courseId.getSubjectCollection().add(subject);
                courseId = em.merge(courseId);
            }
            for (Coursegroup coursegroupCollectionCoursegroup : subject.getCoursegroupCollection()) {
                coursegroupCollectionCoursegroup.getSubjectCollection().add(subject);
                coursegroupCollectionCoursegroup = em.merge(coursegroupCollectionCoursegroup);
            }
            for (Itemcalificable itemcalificableCollectionItemcalificable : subject.getItemcalificableCollection()) {
                Subject oldSubjectIdOfItemcalificableCollectionItemcalificable = itemcalificableCollectionItemcalificable.getSubjectId();
                itemcalificableCollectionItemcalificable.setSubjectId(subject);
                itemcalificableCollectionItemcalificable = em.merge(itemcalificableCollectionItemcalificable);
                if (oldSubjectIdOfItemcalificableCollectionItemcalificable != null) {
                    oldSubjectIdOfItemcalificableCollectionItemcalificable.getItemcalificableCollection().remove(itemcalificableCollectionItemcalificable);
                    oldSubjectIdOfItemcalificableCollectionItemcalificable = em.merge(oldSubjectIdOfItemcalificableCollectionItemcalificable);
                }
            }
            for (Absence absenceCollectionAbsence : subject.getAbsenceCollection()) {
                Subject oldSubjectIdOfAbsenceCollectionAbsence = absenceCollectionAbsence.getSubjectId();
                absenceCollectionAbsence.setSubjectId(subject);
                absenceCollectionAbsence = em.merge(absenceCollectionAbsence);
                if (oldSubjectIdOfAbsenceCollectionAbsence != null) {
                    oldSubjectIdOfAbsenceCollectionAbsence.getAbsenceCollection().remove(absenceCollectionAbsence);
                    oldSubjectIdOfAbsenceCollectionAbsence = em.merge(oldSubjectIdOfAbsenceCollectionAbsence);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findSubject(subject.getId()) != null) {
                throw new PreexistingEntityException("Subject " + subject + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Subject subject) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Subject persistentSubject = em.find(Subject.class, subject.getId());
            Course courseIdOld = persistentSubject.getCourseId();
            Course courseIdNew = subject.getCourseId();
            Collection<Coursegroup> coursegroupCollectionOld = persistentSubject.getCoursegroupCollection();
            Collection<Coursegroup> coursegroupCollectionNew = subject.getCoursegroupCollection();
            Collection<Itemcalificable> itemcalificableCollectionOld = persistentSubject.getItemcalificableCollection();
            Collection<Itemcalificable> itemcalificableCollectionNew = subject.getItemcalificableCollection();
            Collection<Absence> absenceCollectionOld = persistentSubject.getAbsenceCollection();
            Collection<Absence> absenceCollectionNew = subject.getAbsenceCollection();
            List<String> illegalOrphanMessages = null;
            for (Itemcalificable itemcalificableCollectionOldItemcalificable : itemcalificableCollectionOld) {
                if (!itemcalificableCollectionNew.contains(itemcalificableCollectionOldItemcalificable)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Itemcalificable " + itemcalificableCollectionOldItemcalificable + " since its subjectId field is not nullable.");
                }
            }
            for (Absence absenceCollectionOldAbsence : absenceCollectionOld) {
                if (!absenceCollectionNew.contains(absenceCollectionOldAbsence)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Absence " + absenceCollectionOldAbsence + " since its subjectId field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (courseIdNew != null) {
                courseIdNew = em.getReference(courseIdNew.getClass(), courseIdNew.getId());
                subject.setCourseId(courseIdNew);
            }
            Collection<Coursegroup> attachedCoursegroupCollectionNew = new ArrayList<Coursegroup>();
            for (Coursegroup coursegroupCollectionNewCoursegroupToAttach : coursegroupCollectionNew) {
                coursegroupCollectionNewCoursegroupToAttach = em.getReference(coursegroupCollectionNewCoursegroupToAttach.getClass(), coursegroupCollectionNewCoursegroupToAttach.getId());
                attachedCoursegroupCollectionNew.add(coursegroupCollectionNewCoursegroupToAttach);
            }
            coursegroupCollectionNew = attachedCoursegroupCollectionNew;
            subject.setCoursegroupCollection(coursegroupCollectionNew);
            Collection<Itemcalificable> attachedItemcalificableCollectionNew = new ArrayList<Itemcalificable>();
            for (Itemcalificable itemcalificableCollectionNewItemcalificableToAttach : itemcalificableCollectionNew) {
                itemcalificableCollectionNewItemcalificableToAttach = em.getReference(itemcalificableCollectionNewItemcalificableToAttach.getClass(), itemcalificableCollectionNewItemcalificableToAttach.getId());
                attachedItemcalificableCollectionNew.add(itemcalificableCollectionNewItemcalificableToAttach);
            }
            itemcalificableCollectionNew = attachedItemcalificableCollectionNew;
            subject.setItemcalificableCollection(itemcalificableCollectionNew);
            Collection<Absence> attachedAbsenceCollectionNew = new ArrayList<Absence>();
            for (Absence absenceCollectionNewAbsenceToAttach : absenceCollectionNew) {
                absenceCollectionNewAbsenceToAttach = em.getReference(absenceCollectionNewAbsenceToAttach.getClass(), absenceCollectionNewAbsenceToAttach.getId());
                attachedAbsenceCollectionNew.add(absenceCollectionNewAbsenceToAttach);
            }
            absenceCollectionNew = attachedAbsenceCollectionNew;
            subject.setAbsenceCollection(absenceCollectionNew);
            subject = em.merge(subject);
            if (courseIdOld != null && !courseIdOld.equals(courseIdNew)) {
                courseIdOld.getSubjectCollection().remove(subject);
                courseIdOld = em.merge(courseIdOld);
            }
            if (courseIdNew != null && !courseIdNew.equals(courseIdOld)) {
                courseIdNew.getSubjectCollection().add(subject);
                courseIdNew = em.merge(courseIdNew);
            }
            for (Coursegroup coursegroupCollectionOldCoursegroup : coursegroupCollectionOld) {
                if (!coursegroupCollectionNew.contains(coursegroupCollectionOldCoursegroup)) {
                    coursegroupCollectionOldCoursegroup.getSubjectCollection().remove(subject);
                    coursegroupCollectionOldCoursegroup = em.merge(coursegroupCollectionOldCoursegroup);
                }
            }
            for (Coursegroup coursegroupCollectionNewCoursegroup : coursegroupCollectionNew) {
                if (!coursegroupCollectionOld.contains(coursegroupCollectionNewCoursegroup)) {
                    coursegroupCollectionNewCoursegroup.getSubjectCollection().add(subject);
                    coursegroupCollectionNewCoursegroup = em.merge(coursegroupCollectionNewCoursegroup);
                }
            }
            for (Itemcalificable itemcalificableCollectionNewItemcalificable : itemcalificableCollectionNew) {
                if (!itemcalificableCollectionOld.contains(itemcalificableCollectionNewItemcalificable)) {
                    Subject oldSubjectIdOfItemcalificableCollectionNewItemcalificable = itemcalificableCollectionNewItemcalificable.getSubjectId();
                    itemcalificableCollectionNewItemcalificable.setSubjectId(subject);
                    itemcalificableCollectionNewItemcalificable = em.merge(itemcalificableCollectionNewItemcalificable);
                    if (oldSubjectIdOfItemcalificableCollectionNewItemcalificable != null && !oldSubjectIdOfItemcalificableCollectionNewItemcalificable.equals(subject)) {
                        oldSubjectIdOfItemcalificableCollectionNewItemcalificable.getItemcalificableCollection().remove(itemcalificableCollectionNewItemcalificable);
                        oldSubjectIdOfItemcalificableCollectionNewItemcalificable = em.merge(oldSubjectIdOfItemcalificableCollectionNewItemcalificable);
                    }
                }
            }
            for (Absence absenceCollectionNewAbsence : absenceCollectionNew) {
                if (!absenceCollectionOld.contains(absenceCollectionNewAbsence)) {
                    Subject oldSubjectIdOfAbsenceCollectionNewAbsence = absenceCollectionNewAbsence.getSubjectId();
                    absenceCollectionNewAbsence.setSubjectId(subject);
                    absenceCollectionNewAbsence = em.merge(absenceCollectionNewAbsence);
                    if (oldSubjectIdOfAbsenceCollectionNewAbsence != null && !oldSubjectIdOfAbsenceCollectionNewAbsence.equals(subject)) {
                        oldSubjectIdOfAbsenceCollectionNewAbsence.getAbsenceCollection().remove(absenceCollectionNewAbsence);
                        oldSubjectIdOfAbsenceCollectionNewAbsence = em.merge(oldSubjectIdOfAbsenceCollectionNewAbsence);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = subject.getId();
                if (findSubject(id) == null) {
                    throw new NonexistentEntityException("The subject with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Subject subject;
            try {
                subject = em.getReference(Subject.class, id);
                subject.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The subject with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Collection<Itemcalificable> itemcalificableCollectionOrphanCheck = subject.getItemcalificableCollection();
            for (Itemcalificable itemcalificableCollectionOrphanCheckItemcalificable : itemcalificableCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Subject (" + subject + ") cannot be destroyed since the Itemcalificable " + itemcalificableCollectionOrphanCheckItemcalificable + " in its itemcalificableCollection field has a non-nullable subjectId field.");
            }
            Collection<Absence> absenceCollectionOrphanCheck = subject.getAbsenceCollection();
            for (Absence absenceCollectionOrphanCheckAbsence : absenceCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Subject (" + subject + ") cannot be destroyed since the Absence " + absenceCollectionOrphanCheckAbsence + " in its absenceCollection field has a non-nullable subjectId field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Course courseId = subject.getCourseId();
            if (courseId != null) {
                courseId.getSubjectCollection().remove(subject);
                courseId = em.merge(courseId);
            }
            Collection<Coursegroup> coursegroupCollection = subject.getCoursegroupCollection();
            for (Coursegroup coursegroupCollectionCoursegroup : coursegroupCollection) {
                coursegroupCollectionCoursegroup.getSubjectCollection().remove(subject);
                coursegroupCollectionCoursegroup = em.merge(coursegroupCollectionCoursegroup);
            }
            em.remove(subject);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Subject> findSubjectEntities() {
        return findSubjectEntities(true, -1, -1);
    }

    public List<Subject> findSubjectEntities(int maxResults, int firstResult) {
        return findSubjectEntities(false, maxResults, firstResult);
    }

    private List<Subject> findSubjectEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Subject as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Subject findSubject(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Subject.class, id);
        } finally {
            em.close();
        }
    }

    public int getSubjectCount() {
        EntityManager em = getEntityManager();
        try {
            return ((Long) em.createQuery("select count(o) from Subject as o").getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
